#include "../threadpool/threadpool.h"
#include <iostream>
// #include <windows.h>

// 首先创建一个任务节点，并且将任务节点中的函数指针，指向处理任务的执行函数， 然后唤醒线程池中的一个线程来执行任务。
void fun1(int slp)
{
    if (slp > 0)
    {
        printf(" ======= fun1 sleep %d  =========  %d\n", slp, std::this_thread::get_id());
        std::this_thread::sleep_for(std::chrono::milliseconds(slp));
    }
    else
    {
        printf("hello, fun1 !  %d\n", std::this_thread::get_id());
    }
}

int fun2()
{
    return 100;
}

struct gfun
{
    int operator()(int n)
    {
        printf("%d  hello, gfun !  %d\n", n, std::this_thread::get_id());
        return 42;
    }
};

class A
{ //函数必须是 static 的才能使用线程池
public:
    static int Afun(int n = 0)
    {
        std::cout << n << "  hello, Afun !  " << std::this_thread::get_id() << std::endl;
        return n;
    }

    static std::string Bfun(int n, std::string str, char c)
    {
        std::cout << n << "  hello, Bfun !  " << str.c_str() << "  " << (int)c << "  " << std::this_thread::get_id() << std::endl;
        return str;
    }
};

class Dog
{
public:
    void sayHello()
    {
        printf("Dog say hello\r\n");
    }
};

int main()
try
{
    // 第一轮测试
    Dog a;
    gfun b;
    hyf::ThreadPool executor(50);                         //创建线程池对象
    std::future<void> ff = executor.commit(fun1, 0);      // 普通函数
    std::future<int> fg = executor.commit(gfun(), 0);     // 仿函数
    std::future<int> fg1 = executor.commit(b, 1);         // 仿函数
    std::future<int> gg = executor.commit(A::Afun, 9999); // 静态成员函数
    std::future<int> hg = executor.commitCallable(::fun2);
    std::future<int> op =
        executor.commitCallable([]() -> int
                                { return 1300; });
    std::cout << "*******************" << op.get() << std::endl;

    std::future<std::string> gh = executor.commit(A::Bfun, 9998, "mult args", 123); // 静态成员函数
    executor.commit(std::bind(&Dog::sayHello, &a));                                 // 非静态成员函数与非静态成员函数(仿函数)需要bind绑定通过适配器对象调用，如果没有进行bind适配则无法判断出返回值类型，则会编译出错
    executor.commit(std::bind(&Dog::sayHello, a));
    std::future<std::string> fh = executor.commit([]() -> std::string
                                                  {
                                                      std::cout << "hello, fh !  " << std::this_thread::get_id() << std::endl;
                                                      return "hello,fh ret !";
                                                  });                                    // 匿名函数
    std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl; // 获取主线程的id
    std::this_thread::sleep_for(std::chrono::microseconds(900));

    for (int i = 0; i < 50; i++)
    {
        executor.commit(fun1, i * 100);
    }
    std::cout << " ======= commit all ========= " << std::this_thread::get_id() << " idlsize=" << executor.IdlCount() << std::endl;

    std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));

    ff.get(); //调用.get()获取返回值会等待线程执行完,获取返回值
    std::cout << fg.get() << "  " << fh.get().c_str() << "  " << std::this_thread::get_id() << std::endl;
    std::cout << "%%%%%" << hg.get() << std::endl;
    std::cout << " ======= sleep ========= " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));

    std::cout << " ======= fun1,55 ========= " << std::this_thread::get_id() << std::endl;
    executor.commit(fun1, 55).get(); //调用.get()获取返回值会等待线程执行完

    std::cout << "end... " << std::this_thread::get_id() << std::endl;

    // 第二轮测试
    hyf::ThreadPool pool(4);
    std::cout << pool.IdlCount() << ":idl" << std::endl;
    std::vector<std::future<int>> results; // 获取异步结果

    for (int i = 0; i < 8; ++i)
    {
        results.emplace_back(
            pool.commit([i]
                        {
                            std::cout << "hello " << i << std::endl;
                            std::this_thread::sleep_for(std::chrono::seconds(1));
                            std::cout << "world " << i << std::endl;
                            return i * i;
                        }));
    }
    std::cout << " ======= commit all2 ========= " << std::this_thread::get_id() << std::endl;

    for (auto &&result : results)
        std::cout << result.get() << ' ';
    std::cout << std::endl;
    return 0;
}
catch (std::exception &e)
{
    std::cout << "some unhappy happened...  " << std::this_thread::get_id() << e.what() << std::endl;
}
